Skip to content

Conversation

@SorYoshino
Copy link
Contributor

@SorYoshino SorYoshino commented Dec 14, 2025

Summary

Switches calibre to the MSI installer for improved maintainability, adds automatic user data migration, environment variables for portable-like behavior, and registers URL protocol handlers. Marks calibre-normal as deprecated.

Related issues or pull requests

Changes

  • Deprecate calibre-normal after 2026-12-01
  • Switche calibre from portable installer to MSI installer
  • Introduce register-url-handler.reg for registering the calibre: protocol
  • Add pre_install and post_install scripts to migrate user configuration and library
  • Set environment variables: CALIBRE_TEMP_DIR, CALIBRE_CACHE_DIRECTORY, CALIBRE_CONFIG_DIRECTORY
  • Update bin and shortcuts fields for the MSI structure
  • Add uninstaller script to remove URL handlers and file associations
  • Update checkver and autoupdate to use MSI-based URLs

Notes

  • calibre now resolves issues with unregistered URL protocols and residual file associations after uninstallation
uninstall
  • The notes regarding the discontinued 32-bit version were added to the manifest in 2022, and it has now been three years, so I have not re-included them in the notes field. The relevant output is already sufficient.

    ┏[ ~]
    └─> jq '{notes}' "D:\Software\Scoop\Local\buckets\Extras\bucket\calibre-normal.json"
    {
      "notes": "Calibre drops support for 32-bit CPUs after v6.0.0, if you are running a 32-bit system, please install calibre-normal5 from Versions bucket."
    }
    
    ┏[ ~]
    └─> scoop install Extras/calibre-normal --arch 32bit
    ERROR 'calibre-normal' doesn't support current architecture!
  • The tests described in this PR are not comprehensive and only cover the installation of calibre-normal. Data migration tests are divided into the following four scenarios. Click the corresponding links to view the testing methods and results.

  • When the windows_register_default_programs field in gui.json is missing or its value does not match the currently installed version, running calibre.exe will automatically register file associations, writing the relevant registry entries to HKCU. Therefore, this PR does not provide a script to register file associations. At the same time, unregister-file-associations.reg only needs to be copied to $dir.

  • To ensure a one-to-one correspondence between registered file association entries and $global, the environment variable CALIBRE_NO_DEFAULT_PROGRAMS is used to prevent the application from automatically registering related file associations. The install-associations.reg file is then provided so that users can decide whether to register the file associations manually.

Testing

The test results are as follows:
┏[ ~]
└─> scoop install Unofficial/calibre-normal
Installing 'calibre-normal' (8.16.2) [64bit] from 'Unofficial' bucket
Loading calibre-64bit-8.16.2.msi from cache.
Checking hash of calibre-64bit-8.16.2.msi ... ok.
Extracting calibre-64bit-8.16.2.msi ... done.
Linking D:\Software\Others\Scoop\Local\apps\calibre-normal\current => D:\Software\Others\Scoop\Local\apps\calibre-normal\8.16.2
Creating shim for 'calibre'.
Making D:\Software\Others\Scoop\Local\shims\calibre.exe a GUI binary.
Creating shim for 'calibre-complete'.
Creating shim for 'calibre-customize'.
Creating shim for 'calibredb'.
Creating shim for 'calibre-debug'.
Creating shim for 'calibre-parallel'.
Creating shim for 'calibre-server'.
Creating shim for 'calibre-smtp'.
Creating shim for 'ebook-convert'.
Creating shim for 'ebook-device'.
Creating shim for 'ebook-edit'.
Making D:\Software\Others\Scoop\Local\shims\ebook-edit.exe a GUI binary.
Creating shim for 'ebook-meta'.
Creating shim for 'ebook-polish'.
Creating shim for 'ebook-viewer'.
Making D:\Software\Others\Scoop\Local\shims\ebook-viewer.exe a GUI binary.
Creating shim for 'fetch-ebook-metadata'.
Creating shim for 'lrf2lrs'.
Creating shim for 'lrs2lrf'.
Creating shim for 'lrfviewer'.
Making D:\Software\Others\Scoop\Local\shims\lrfviewer.exe a GUI binary.
Creating shim for 'markdown-calibre'.
Creating shim for 'web2disk'.
Creating shortcut for Calibre (calibre.exe)
Creating shortcut for Calibre E-Book Editor (ebook-edit.exe)
Creating shortcut for Calibre E-Book Viewer (ebook-viewer.exe)
Creating shortcut for Calibre LRF Viewer (lrfviewer.exe)
'calibre-normal' (8.16.2) was installed successfully!
Notes
-----
`calibre` has been switched to the MSI installer, providing portable-like functionality through the use of environment variables.
User data will be migrated automatically during the installation process of `calibre`, so there is no need to worry about data loss.
`calibre` also resolves issues related to unregistered URL protocol handlers and residual file associations after uninstallation.
This manifest will be deprecated on 2026-12-01. Please install `extras/calibre` instead.
  • Use conventional PR title: <manifest-name[@version]|chore>: <general summary of the pull request>
  • I have read the Contributing Guide

Summary by CodeRabbit

  • New Features

    • Adds URL protocol handler and broad file-association registration so Calibre can open many e-book/document formats directly.
  • Improvements

    • Migrated installer flow to MSI for improved system integration.
    • Automatic migration of user settings/libraries to a persistent location during install.
    • Cleaner uninstall handling for associations and URL handlers.
  • Chores

    • License updated to GPL-3.0-or-later; manifest marked for deprecation after 2026-12-01.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 14, 2025

Walkthrough

Migrates Calibre from a portable to MSI-based installation, adds pre/post-install and uninstaller scripts for settings/library migration, converts manifest metadata types (license, notes), and adds comprehensive registry scripts to register/unregister file associations and the calibre:// URL protocol.

Changes

Cohort / File(s) Summary
Manifest metadata updates
bucket/calibre-normal.json, bucket/calibre.json
Converted license string to object (identifier, url), appended periods to description, changed notes from string to array, added top-level deprecation ## in calibre-normal.json.
Installer workflow & manifest overhaul (MSI migration)
bucket/calibre.json
Switched 64bit download/autoupdate to MSI-based URLs; added pre_install, post_install, and uninstaller blocks to migrate settings/libraries and unregister handlers; replaced portable bin entries with MSI paths (added calibredb.exe); updated shortcuts, env_set, persist, and installer logic to use MSI layout.
URL protocol registration scripts
scripts/calibre/register-url-handler.reg, scripts/calibre/unregister-url-handler.reg
Added registry export to register calibre:// protocol (DefaultIcon, URL Protocol, command invoking calibre.exe "%1") and companion script to remove the HKCU\Software\Classes\calibre key on uninstall.
File association registry scripts
scripts/calibre/install-associations.reg, scripts/calibre/uninstall-associations.reg
Added large, repetitive registry exports to register/unregister Calibre as OpenWith/Default handler for numerous extensions (EPUB, PDF, MOBI, AZW*, CBZ/CBR, DOC/DOCX, RTF, TXT, HTML, etc.), mapping viewer/editor classes to calibre executables and removing them on uninstall.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User
    participant Scoop as "Scoop"
    participant PS as "PowerShell scripts"
    participant MSI as "MSI Installer"
    participant Registry as "Windows Registry"
    participant Calibre as "Calibre App"

    rect rgb(240,247,255)
    User->>Scoop: scoop install calibre
    Scoop->>PS: run pre_install (migrate settings)
    PS-->>Scoop: migration complete
    end

    rect rgb(255,248,230)
    Scoop->>MSI: download & run MSI installer
    MSI->>Calibre: place files into Program Files
    MSI-->>Scoop: install complete
    end

    rect rgb(246,255,242)
    Scoop->>PS: run post_install (migrate libraries, create shortcuts)
    PS->>Registry: apply install-associations.reg & register-url-handler.reg
    Registry-->>PS: keys/values created
    PS-->>Scoop: post-install complete
    end

    rect rgb(255,240,246)
    User->>Calibre: open calibre://... or double-click file
    Calibre->>Registry: query protocol/file association
    Registry-->>Calibre: return command (calibre.exe "%1")
    Calibre->>Calibre: launch with argument
    end

    rect rgb(248,248,248)
    User->>Scoop: scoop uninstall calibre
    Scoop->>PS: run uninstaller (unregister associations, cleanup)
    PS->>Registry: apply uninstall-associations.reg & unregister-url-handler.reg
    Registry-->>PS: keys/values removed
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • z-Fng

Poem

🐇 I hopped through manifests, tidy and spry,

From portable burrow to MSI sky-high,
Registry carrots line the trail,
Libraries moved without fail,
Calibre hops, pouch full of joy!

Pre-merge checks

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'calibre: Switch to MSI Installer' clearly and concisely summarizes the main change in the changeset—migrating from portable to MSI installer.
Description check ✅ Passed The description includes a comprehensive summary, related issues/PRs, detailed change list, testing results, and notes. It follows the repository's template structure with proper issue references and conventional formatting.
Linked Issues check ✅ Passed The PR addresses all primary coding objectives from linked issues: #15348 (eliminated GUI prompts and long path issues via MSI), #12659 (added URL protocol registration via register-url-handler.reg), and provides file association handling.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the MSI migration objective: manifest updates, migration scripts, registry handlers, environment variable setup, and deprecation notice. No unrelated modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

All changes look good.

Wait for review from human collaborators.

calibre-normal

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate
  • Autoupdate Hash Extraction

calibre

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate
  • Autoupdate Hash Extraction

Check the full log for details.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
bucket/calibre.json (1)

96-113: Consider simplifying the main shortcut name.

Line 99 creates a shortcut path "Calibre - E-book Management\Calibre - E-book Management", resulting in a redundant name. Consider shortening the shortcut name to just "Calibre" since it's already within the "Calibre - E-book Management" folder:

         [
             "Calibre\\calibre.exe",
-            "Calibre - E-book Management\\Calibre - E-book Management"
+            "Calibre - E-book Management\\Calibre"
         ],

This would make it consistent with the other shortcuts (E-Book Editor, E-Book Viewer, LRF Viewer) which don't repeat "Calibre" in their names.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 08b9553 and a951118.

📒 Files selected for processing (5)
  • bucket/calibre-normal.json (1 hunks)
  • bucket/calibre.json (2 hunks)
  • scripts/calibre/register-url-handler.reg (1 hunks)
  • scripts/calibre/unregister-file-associations.reg (1 hunks)
  • scripts/calibre/unregister-url-handler.reg (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: WindowsPowerShell
🔇 Additional comments (13)
scripts/calibre/unregister-file-associations.reg (1)

3-3: LGTM: Calibre settings cleanup on uninstall.

Removing the main calibre registry key during uninstall is appropriate for cleanup.

bucket/calibre.json (8)

19-32: Review migration logic and conditional flow.

The pre_install migration has several considerations:

  1. Lines 21-22: The conditional checks if settings exist OR if env var already points to persist_dir. The second condition appears to be the expected state (env var should point to persist_dir), so returning early when it's already configured correctly is logical.

  2. Lines 23-27: Migrates from custom CALIBRE_CONFIG_DIRECTORY and returns, preventing fallthrough to APPDATA migration. This prioritization seems correct—honor user's explicit env var over default location.

  3. Lines 28-31: Falls back to migrating from default APPDATA location only if previous conditions weren't met.

The logic appears sound for handling multiple migration scenarios (fresh install, env var user, default APPDATA user).


34-45: LGTM: Installer cleanup logic handles migration scenarios.

The installer script properly:

  • Identifies and removes conflicting configuration directories (symlinks from calibre-normal, custom env var locations)
  • Extracts the MSI content to the expected location
  • Uses conditional array building (lines 40, 42) to only include directories that need cleanup

This cleanup prevents conflicts when migrating from calibre-normal's symlink approach.


47-54: LGTM: Registry template processing with proper escaping and global install handling.

The post_install script correctly:

  • Escapes backslashes for Windows registry format (line 48)
  • Processes all .reg templates from the scripts directory
  • Conditionally replaces HKEY_CURRENT_USER with HKEY_LOCAL_MACHINE for global installs, except for the unregister script which should always target the current user
  • Substitutes the calibre installation path into templates

71-75: LGTM: Environment variables provide portable-like behavior.

The environment variables correctly point Calibre to persisted directories, achieving portable-like functionality with the MSI installer as described in the PR objectives.


76-95: LGTM: Bin entries updated for MSI installer layout.

The bin entries correctly reflect the MSI installer's directory structure with the Calibre\ subdirectory prefix.


118-125: LGTM: Uninstaller properly cleans up registry entries.

The uninstaller correctly:

  • Checks for uninstall command to avoid running during upgrades
  • Removes URL handler registration
  • Removes file associations

This addresses the PR objective of cleaning up residual registry entries.


129-138: LGTM: Autoupdate configured for MSI installer.

The autoupdate section correctly uses the MSI URL format, consistent with the manual URL definition.


9-12: The manual URL handler registration instruction is necessary and correctly documented. The post_install script (lines 49-54) only generates and prepares the registry file with template substitution; it does not automatically import it. The script copies register-url-handler.reg from the extras/scripts directory to $dir but stops there. Users must manually execute the reg import command to activate the URL protocol handler. This pattern is consistent with the uninstaller (lines 121-122), which explicitly imports the unregister registry files.

bucket/calibre-normal.json (2)

2-15: LGTM: Clear deprecation notice with migration path.

The manifest properly communicates:

  • Deprecation timeline (2026-12-01)
  • Benefits of migrating to extras/calibre
  • Automatic data migration
  • Resolution of URL protocol and file association issues

This gives users ample time to transition.


16-76: LGTM: Simplified manifest appropriate for deprecated package.

This deprecated manifest provides basic MSI extraction without the migration scripts, portable behavior, or registry cleanup. This is appropriate as users are encouraged to migrate to the main calibre manifest.

scripts/calibre/unregister-url-handler.reg (1)

1-3: LGTM: URL handler unregistration is correct.

The registry script properly removes the calibre URL protocol registration by deleting the protocol key.

scripts/calibre/register-url-handler.reg (1)

3-15: LGTM: URL protocol registration follows Windows conventions.

The registry script correctly implements Windows URL protocol registration with:

  • Protocol identifier and description (lines 3-5)
  • Icon specification using template variable (lines 7-8)
  • Shell command association with URL argument placeholder (lines 10-15)

The template variable {{calibre_dir}} will be substituted during post_install (bucket/calibre.json line 53), resolving issue #12659.

@SorYoshino SorYoshino marked this pull request as draft December 14, 2025 16:59
@SorYoshino
Copy link
Contributor Author

/verify

@SorYoshino SorYoshino marked this pull request as ready for review December 14, 2025 17:40
@github-actions
Copy link
Contributor

All changes look good.

Wait for review from human collaborators.

calibre-normal

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate
  • Autoupdate Hash Extraction

calibre

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate
  • Autoupdate Hash Extraction

Check the full log for details.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
bucket/calibre.json (1)

49-53: Silent failure if registry scripts directory doesn't exist.

Lines 49–53 process registry templates from $bucketsdir\\extras\\scripts\\$app, but the directory path is never verified to exist. If the directory is missing, Get-ChildItem will silently fail (due to line 36's $ErrorActionPreference = 'SilentlyContinue'), and registry files won't be created in $dir. This means URL handlers and file associations won't be registered.

Consider adding a check or warning if no registry scripts are found:

$registryScripts = @(Get-ChildItem -Path "$bucketsdir\\extras\\scripts\\$app" -Filter '*.reg' -File -ErrorAction SilentlyContinue)
if ($registryScripts.Count -eq 0) {
    Write-Host "WARNING: No registry scripts found for URL handler registration" -ForegroundColor Yellow
    return
}
$registryScripts | ForEach-Object {
    ...
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a951118 and 9f66a87.

📒 Files selected for processing (5)
  • bucket/calibre-normal.json (1 hunks)
  • bucket/calibre.json (2 hunks)
  • scripts/calibre/register-url-handler.reg (1 hunks)
  • scripts/calibre/unregister-file-associations.reg (1 hunks)
  • scripts/calibre/unregister-url-handler.reg (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • bucket/calibre-normal.json
  • scripts/calibre/unregister-file-associations.reg
  • scripts/calibre/register-url-handler.reg
  • scripts/calibre/unregister-url-handler.reg
🔇 Additional comments (9)
bucket/calibre.json (9)

1-11: Metadata updates aligned with MSI migration.

License change from GPL-3.0-only to GPL-3.0-or-later with HEAD reference, and notes about URL protocol registration are appropriate additions. Description formatting is consistent.


19-31: Configuration migration logic is sound.

The pre_install script correctly handles three migration scenarios:

  1. Early return if Calibre Settings already exist
  2. Priority to CALIBRE_CONFIG_DIRECTORY environment variable if set
  3. Fallback to %APPDATA%\calibre for standard installations

This aligns with the PR objectives for supporting environment variable–based portability.


55-69: Library migration logic maintains data integrity.

The logic correctly:

  • Checks if new location is empty and source has content (line 62) before attempting migration
  • Copies library data (line 64)
  • Updates configuration (line 67–68)

As clarified in prior review feedback, the unconditional removal on line 66 is safe because the early return on line 61 ensures paths are different, and the condition on line 62 ensures the source has content while the destination is empty.

One edge case: if Copy-Item fails silently due to global $ErrorActionPreference = 'SilentlyContinue' (line 36), the Remove-Item will still execute. However, this is a rare scenario and Scoop's use of silent error suppression is standard practice.

Consider verifying the Copy-Item success explicitly to prevent data loss in edge cases:

if (-not (Test-Path "$persist_dir\\Calibre Library\\*\") -and (Test-Path "$($cfg.library_path)\\*")) {
    Write-Host \"`nINFO  Migrating Calibre Library to \"$persist_dir\\Calibre Library\"...\" -ForegroundColor darkgray
    Copy-Item -Path "$($cfg.library_path)\\*" -Destination "$persist_dir\\Calibre Library" -Force -Recurse
+   if (Test-Path "$persist_dir\\Calibre Library\\*\") {
        Remove-Item -Path $cfg.library_path -Force -Recurse -ErrorAction SilentlyContinue
+   } else {
+       Write-Host "ERROR: Library migration failed, old location preserved" -ForegroundColor Red
+   }
}

71-75: Environment variables enable portable-like behavior.

The env_set block correctly defines the three environment variables needed to support portable-style behavior with MSI installations:

  • CALIBRE_TEMP_DIR, CALIBRE_CACHE_DIRECTORY, and CALIBRE_CONFIG_DIRECTORY all point to the persistent user data directory

This satisfies the PR objectives for supporting portable-like configurations.


76-94: Binary paths updated for MSI layout.

All binaries correctly point to the Calibre\ subdirectory (created by line 44's MSI extraction). The addition of calibredb.exe (line 82) aligns with the MSI package contents. Path consistency is maintained across all entries.


96-112: Shortcuts refactored for consistent menu structure.

Menu items reorganized under the "Calibre - E-book Management" category. All four primary shortcuts (main app, editor, viewer, LRF viewer) are present with updated paths. Structure is clean and user-friendly.


118-125: Uninstaller cleanly removes URL handlers and file associations.

The uninstaller script imports two registry files to clean up:

  • unregister-url-handler.reg (removes calibre:// protocol handler)
  • unregister-file-associations.reg (removes e-book file type associations)

This addresses PR objective #12659 (URL protocol issues) by ensuring a clean uninstall. The conditional if ($cmd -eq 'uninstall') guard is appropriate.


129-137: Autoupdate URL pattern correctly reflects MSI format.

The URL pattern https://download.calibre-ebook.com/$version/calibre-64bit-$version.msi#/dl.msi_ matches the initial installer URL (line 15) and correctly extracts the MSI with the #/dl.msi_ fragment. Hash lookup from calibre-ebook.com/signatures is appropriate.


44-44: No action required. The Expand-MsiArchive function with -ExtractDir and -Removal parameters is a standard Scoop utility. Both parameters are confirmed as supported and properly used in the calibre.json manifest, consistent with their usage across multiple official Scoop Extras manifests including sonic-pi.json, powertoys.json, enpass.json, and boinc.json.

@SorYoshino SorYoshino marked this pull request as draft December 16, 2025 11:06
@SorYoshino
Copy link
Contributor Author

/verify

@github-actions
Copy link
Contributor

All changes look good.

Wait for review from human collaborators.

calibre-normal

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate
  • Autoupdate Hash Extraction

calibre

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate
  • Autoupdate Hash Extraction

Check the full log for details.

@SorYoshino SorYoshino marked this pull request as ready for review December 16, 2025 12:21
@SorYoshino
Copy link
Contributor Author

/verify

@github-actions
Copy link
Contributor

All changes look good.

Wait for review from human collaborators.

calibre-normal

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate
  • Autoupdate Hash Extraction

calibre

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate
  • Autoupdate Hash Extraction

Check the full log for details.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
scripts/calibre/unregister-file-associations.reg (1)

356-359: Consider adding a trailing newline.

The file ends abruptly after line 359. While most registry import tools handle this gracefully, adding a trailing blank line ensures compatibility with all tools and follows common convention for text files.

 [-HKEY_CURRENT_USER\Software\Classes\calibre64bit.AssocFile.XPS]
+
bucket/calibre.json (1)

36-43: Clarify the array multiplication pattern for maintainability.

The pattern @($value) * $is_different on lines 40 and 42 is clever but non-obvious. When $is_different is $false (coerced to 0), it produces an empty array, effectively filtering out values.

$link_target_dir = @($config_link_target_dir) * $is_different

This works but may confuse future maintainers. A brief inline comment or using a more explicit conditional would improve readability.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 96ded73 and 4f0d639.

📒 Files selected for processing (5)
  • bucket/calibre-normal.json (1 hunks)
  • bucket/calibre.json (2 hunks)
  • scripts/calibre/register-url-handler.reg (1 hunks)
  • scripts/calibre/unregister-file-associations.reg (1 hunks)
  • scripts/calibre/unregister-url-handler.reg (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • scripts/calibre/unregister-url-handler.reg
  • scripts/calibre/register-url-handler.reg
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-13T09:37:06.093Z
Learnt from: o-l-a-v
Repo: ScoopInstaller/Extras PR: 16328
File: bucket/winutil.json:0-0
Timestamp: 2025-10-13T09:37:06.093Z
Learning: When reviewing code in Scoop manifests, always verify the actual file content if the diff appears incomplete or unusual, as diff context can be truncated or displayed incorrectly. The pattern `[string[]](...).ForEach{...}` is commonly used in post_uninstall scripts across the Extras repository.

Applied to files:

  • bucket/calibre.json
📚 Learning: 2025-10-15T11:54:31.320Z
Learnt from: o-l-a-v
Repo: ScoopInstaller/Extras PR: 16341
File: bucket/foxit-pdf-reader.json:47-50
Timestamp: 2025-10-15T11:54:31.320Z
Learning: In bucket/foxit-pdf-reader.json and bucket/foxit-reader.json, the checkver script uses MaximumRedirection 1 (not 0) for Invoke-WebRequest to properly handle Foxit's backend redirect behavior when parsing the Location header for version detection.

Applied to files:

  • bucket/calibre.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: WindowsPowerShell
🔇 Additional comments (7)
bucket/calibre-normal.json (2)

10-15: Well-structured deprecation notes with clear migration guidance.

The notes provide helpful context for users, explaining the MSI switch, automatic data migration, and the deprecation timeline. The inline reference to extras/calibre is appropriate for this repository.


6-9: License metadata properly structured.

Using the SPDX identifier GPL-3.0-or-later with a direct link to the LICENSE file follows best practices for Scoop manifest metadata.

scripts/calibre/unregister-file-associations.reg (1)

1-3: Clean registry cleanup script structure.

The script properly deletes the calibre software key and systematically removes all file associations. The casing for OpenWithProgIDs is now consistent throughout the file.

bucket/calibre.json (4)

9-12: Manual URL protocol registration may confuse users.

The notes require users to manually run a reg import command to register the URL protocol handler. This contrasts with the PR objective to "fix missing or broken protocol/file-association registration" automatically.

Consider whether this could be automated in post_install for a better user experience, or if there's a specific reason (like requiring elevation) that necessitates manual execution.


47-54: Backslash escaping is correct for registry format.

The -replace '\\\\', '\\\\' in JSON translates to -replace '\\', '\\' in PowerShell after JSON parsing, which correctly doubles single backslashes for registry path format. This was confirmed working in previous review discussions.


55-69: Library migration logic is sound.

The flow correctly handles:

  1. Fresh install (creates new global.py.json with default library path)
  2. Existing config with matching path (early return on line 61)
  3. Migration from different location (copies if target empty, source has content)

The unconditional removal on line 66 is intentional per the author's explanation—under normal usage, both locations cannot simultaneously contain library files.


118-125: Uninstaller script handles cleanup correctly.

The $cmd -eq 'uninstall' check ensures registry cleanup only runs during actual uninstallation, not during updates. Redirecting output with *> $null silences both success and error messages appropriately.

@SorYoshino SorYoshino marked this pull request as draft December 26, 2025 18:45
@SorYoshino
Copy link
Contributor Author

/verify

@github-actions
Copy link
Contributor

github-actions bot commented Jan 3, 2026

All changes look good.

Wait for review from human collaborators.

calibre

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate
  • Autoupdate Hash Extraction

Check the full log for details.

@SorYoshino
Copy link
Contributor Author

/verify

@github-actions
Copy link
Contributor

github-actions bot commented Jan 3, 2026

All changes look good.

Wait for review from human collaborators.

calibre-normal

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate
  • Autoupdate Hash Extraction

calibre

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate
  • Autoupdate Hash Extraction

Check the full log for details.

@SorYoshino SorYoshino marked this pull request as ready for review January 3, 2026 10:20
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
bucket/calibre.json (1)

45-45: Fix the backslash escaping pattern.

The current pattern -replace '\\\\', '\\\\' looks for two consecutive backslashes in the path, but string interpolation "$dir\\Calibre" produces single backslashes. This makes the replacement a no-op, leaving paths with single backslashes that won't work correctly in registry files expecting double backslashes.

Based on the previous discussion, the correct pattern is -replace '\\', '\\' as demonstrated by SorYoshino's test.

🔎 Proposed fix
-$calibre_dir = "$dir\\Calibre" -replace '\\\\', '\\\\'
+$calibre_dir = "$dir\\Calibre" -replace '\\', '\\'
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4f0d639 and 8dbc622.

📒 Files selected for processing (2)
  • bucket/calibre-normal.json
  • bucket/calibre.json
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-13T09:37:06.093Z
Learnt from: o-l-a-v
Repo: ScoopInstaller/Extras PR: 16328
File: bucket/winutil.json:0-0
Timestamp: 2025-10-13T09:37:06.093Z
Learning: When reviewing code in Scoop manifests, always verify the actual file content if the diff appears incomplete or unusual, as diff context can be truncated or displayed incorrectly. The pattern `[string[]](...).ForEach{...}` is commonly used in post_uninstall scripts across the Extras repository.

Applied to files:

  • bucket/calibre.json
📚 Learning: 2025-10-15T11:54:31.320Z
Learnt from: o-l-a-v
Repo: ScoopInstaller/Extras PR: 16341
File: bucket/foxit-pdf-reader.json:47-50
Timestamp: 2025-10-15T11:54:31.320Z
Learning: In bucket/foxit-pdf-reader.json and bucket/foxit-reader.json, the checkver script uses MaximumRedirection 1 (not 0) for Invoke-WebRequest to properly handle Foxit's backend redirect behavior when parsing the Location header for version detection.

Applied to files:

  • bucket/calibre.json
🔇 Additional comments (7)
bucket/calibre-normal.json (1)

2-15: LGTM! Metadata updates align with deprecation strategy.

The deprecation notice, license object format, and notes array provide clear guidance for users migrating to the MSI-based extras/calibre manifest. The notes effectively communicate the migration timeline and benefits.

bucket/calibre.json (6)

3-14: LGTM! Metadata properly updated for MSI installer.

The license format, description, and notes array appropriately document the MSI-based installation workflow and provide clear instructions for registry operations.


21-29: LGTM! Configuration migration logic is sound.

The pre_install script correctly handles configuration directory migration with appropriate checks to avoid overwriting existing settings.


31-42: LGTM! Installer cleanup logic handles migration edge cases.

The conditional array multiplication pattern correctly handles cleanup of old configuration directories and symlinks before extracting the MSI archive.


68-73: LGTM! Environment variables properly configured for portable-like behavior.

The environment variables correctly point to persisted directories, providing the portable functionality described in the PR objectives.


74-111: LGTM! Bin and shortcuts properly updated for MSI layout.

The paths and shortcut names correctly reflect the MSI installation structure with the Calibre subdirectory.


127-136: LGTM! Autoupdate configuration matches MSI URL format.

The autoupdate block correctly uses MSI-based URLs and hash verification.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
bucket/calibre.json (2)

45-45: Fix backslash escaping pattern for registry file generation.

The current pattern -replace '\\\\', '\\\\' is a no-op because it matches two consecutive backslashes and replaces them with two backslashes. Since Join-Path returns paths with single backslashes (e.g., C:\Users\test\Calibre), this pattern won't match anything, and the registry templates will receive paths with single backslashes instead of the required double backslashes.

The author's own demonstration in past comments showed the correct pattern is -replace '\\', '\\', which doubles each single backslash.

🔎 Proposed fix
-    "$calibre_dir = \"$dir\\Calibre\" -replace '\\\\', '\\\\'",
+    "$calibre_dir = \"$dir\\Calibre\" -replace '\\', '\\'",

119-119: Fix registry filename to match actual unregister file.

Line 119 references uninstall-associations.reg, but:

  • The PR description specifies unregister-file-associations.reg is copied to $dir
  • Line 120 uses the unregister- prefix pattern for URL handlers
  • Past comments identified this issue, and while it was partially fixed (changed from install-associations.reg), the filename is still incorrect

The filename should be unregister-file-associations.reg for consistency with the naming pattern and to match the actual file copied by the post_install script.

🔎 Proposed fix
-            "    reg import \"$dir\\uninstall-associations.reg\" *> $null",
+            "    reg import \"$dir\\unregister-file-associations.reg\" *> $null",
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8dbc622 and 766b649.

📒 Files selected for processing (1)
  • bucket/calibre.json
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-13T09:37:06.093Z
Learnt from: o-l-a-v
Repo: ScoopInstaller/Extras PR: 16328
File: bucket/winutil.json:0-0
Timestamp: 2025-10-13T09:37:06.093Z
Learning: When reviewing code in Scoop manifests, always verify the actual file content if the diff appears incomplete or unusual, as diff context can be truncated or displayed incorrectly. The pattern `[string[]](...).ForEach{...}` is commonly used in post_uninstall scripts across the Extras repository.

Applied to files:

  • bucket/calibre.json
📚 Learning: 2025-10-15T11:54:31.320Z
Learnt from: o-l-a-v
Repo: ScoopInstaller/Extras PR: 16341
File: bucket/foxit-pdf-reader.json:47-50
Timestamp: 2025-10-15T11:54:31.320Z
Learning: In bucket/foxit-pdf-reader.json and bucket/foxit-reader.json, the checkver script uses MaximumRedirection 1 (not 0) for Invoke-WebRequest to properly handle Foxit's backend redirect behavior when parsing the Location header for version detection.

Applied to files:

  • bucket/calibre.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: WindowsPowerShell
🔇 Additional comments (9)
bucket/calibre.json (9)

21-29: LGTM! Pre-install migration logic is well-structured.

The script properly:

  • Ensures the persistent settings directory exists
  • Skips migration if settings are already present
  • Checks standard config locations (environment variable or AppData)
  • Migrates existing configurations when found

30-42: LGTM! Installer cleanup and MSI extraction are correct.

The script appropriately:

  • Removes legacy config directories (default, symlink targets, environment-based) before installation
  • Extracts the MSI to the correct destination with proper path structure

46-50: LGTM! Registry file templating logic is correct.

The script properly:

  • Iterates through all .reg files in the scripts directory
  • Handles global installs by remapping registry hives
  • Substitutes the calibre_dir path template variable
  • Saves processed files with Unicode encoding (required for .reg files)

51-67: LGTM! Settings and library migration logic is sound.

The script correctly:

  • Ensures temporary and cache directories exist
  • Creates default configuration if needed
  • Migrates library content when appropriate (non-empty source, empty target)
  • Updates configuration to point to new library location
  • Uses error suppression for safe cleanup of old paths

Based on the author's prior clarification, the logic correctly handles migration scenarios.


68-73: LGTM! Environment variables correctly support portable-like behavior.

The variables appropriately:

  • Disable default program registration (avoiding system-wide changes)
  • Point temp, cache, and config to persistent directories
  • Align with the persistent directory structure defined in the manifest

74-111: LGTM! Bin and shortcuts correctly reflect MSI structure.

The updates properly:

  • Adjust all executable paths to the MSI-based Calibre\ directory structure
  • Organize shortcuts under "Calibre - E-book Management" folder
  • Use clear, descriptive names for shortcuts

112-115: LGTM! Persist directories are correctly configured.

The persistent directories match those created and referenced throughout the installation and configuration scripts.


124-136: LGTM! Checkver and autoupdate correctly configured for MSI.

The configuration properly:

  • Uses GitHub as the version source
  • Updates the URL pattern to MSI format
  • Retrieves hash verification from the official source

46-50: Registry filename references in manifest are correct.

Verification confirms all registry files referenced in the manifest (lines 11, 13, 119, 120) exist in scripts/calibre/ and match the actual filenames: install-associations.reg, register-url-handler.reg, uninstall-associations.reg, and unregister-url-handler.reg. The post_install script correctly copies all .reg files from the scripts directory.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
bucket/calibre-normal.json (1)

6-8: Revert the license identifier to GPL-3.0-only.

As flagged in a previous review, Calibre is licensed under GNU GPL v3 only (not "or later"). The FSF Free Software Directory explicitly lists GPL-3.0-only for Calibre.

🔎 Proposed fix
     "license": {
-        "identifier": "GPL-3.0-or-later",
+        "identifier": "GPL-3.0-only",
         "url": "https://github.com/kovidgoyal/calibre/blob/HEAD/LICENSE"
     },
bucket/calibre.json (2)

6-7: Revert the license identifier to GPL-3.0-only.

Same issue as in calibre-normal.json — Calibre is licensed under GNU GPL v3 only, not "or later".

🔎 Proposed fix
     "license": {
-        "identifier": "GPL-3.0-or-later",
+        "identifier": "GPL-3.0-only",
         "url": "https://github.com/kovidgoyal/calibre/blob/HEAD/LICENSE"
     },

45-45: Fix the path construction and backslash escaping.

The current approach has issues:

  1. "$dir\\Calibre" uses string concatenation with literal \\ which creates inconsistent paths (single backslash from $dir expansion + double backslash literal)
  2. The -replace '\\\\', '\\\\' is a no-op (replaces 2 backslashes with 2 backslashes)

As discussed in the previous review, use Join-Path for proper path construction and -replace '\\', '\\' for escaping:

🔎 Proposed fix
-        "$calibre_dir = \"$dir\\Calibre\" -replace '\\\\\\\\', '\\\\\\\\'",
+        "$calibre_dir = (Join-Path $dir 'Calibre') -replace '\\\\', '\\\\'",
🧹 Nitpick comments (1)
bucket/calibre.json (1)

59-65: Verify library migration safety in edge cases.

Line 63's Remove-Item executes unconditionally after the migration check. If migration is skipped because the target already has content (line 59), the old library location is still deleted. While the author confirmed this is acceptable for normal usage, consider moving the removal inside the migration block for defensive safety:

🔎 Proposed safer approach
     "    if (-not (Test-Path -Path \"$persist_dir\\Calibre Library\\*\") -and (Test-Path -Path \"$($cfg.library_path)\\*\")) {",
     "        Write-Host \"`nINFO  Migrating Calibre Library to '$persist_dir\\Calibre Library'...\" -ForegroundColor DarkGray",
     "        Copy-Item -Path \"$($cfg.library_path)\\*\" -Destination \"$persist_dir\\Calibre Library\" -Force -Recurse",
+    "        Remove-Item -Path $cfg.library_path -Recurse -Force -ErrorAction SilentlyContinue",
     "    }",
-    "    Remove-Item -Path $cfg.library_path -Recurse -Force -ErrorAction SilentlyContinue",
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 766b649 and 8db552f.

📒 Files selected for processing (6)
  • bucket/calibre-normal.json
  • bucket/calibre.json
  • scripts/calibre/install-associations.reg
  • scripts/calibre/register-url-handler.reg
  • scripts/calibre/uninstall-associations.reg
  • scripts/calibre/unregister-url-handler.reg
🚧 Files skipped from review as they are similar to previous changes (2)
  • scripts/calibre/unregister-url-handler.reg
  • scripts/calibre/register-url-handler.reg
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-13T09:37:06.093Z
Learnt from: o-l-a-v
Repo: ScoopInstaller/Extras PR: 16328
File: bucket/winutil.json:0-0
Timestamp: 2025-10-13T09:37:06.093Z
Learning: When reviewing code in Scoop manifests, always verify the actual file content if the diff appears incomplete or unusual, as diff context can be truncated or displayed incorrectly. The pattern `[string[]](...).ForEach{...}` is commonly used in post_uninstall scripts across the Extras repository.

Applied to files:

  • bucket/calibre.json
📚 Learning: 2025-10-15T11:54:31.320Z
Learnt from: o-l-a-v
Repo: ScoopInstaller/Extras PR: 16341
File: bucket/foxit-pdf-reader.json:47-50
Timestamp: 2025-10-15T11:54:31.320Z
Learning: In bucket/foxit-pdf-reader.json and bucket/foxit-reader.json, the checkver script uses MaximumRedirection 1 (not 0) for Invoke-WebRequest to properly handle Foxit's backend redirect behavior when parsing the Location header for version detection.

Applied to files:

  • bucket/calibre.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: WindowsPowerShell
🔇 Additional comments (6)
bucket/calibre-normal.json (1)

2-15: Deprecation notice and migration notes are well-structured.

The deprecation comment, updated notes array, and clear guidance for users to migrate to extras/calibre are appropriate. The notes effectively communicate the MSI switch, automatic data migration, and deprecation timeline.

scripts/calibre/install-associations.reg (1)

1-1476: File associations registry template is well-structured.

The template correctly:

  • Uses {{calibre_dir}} placeholder for path substitution
  • Registers OpenWithProgIDs with hex(0): (empty REG_NONE value) per Windows convention
  • Creates proper shell command handlers for each file type
  • Maps extensions to appropriate executables (calibre.exe, ebook-viewer.exe, ebook-edit.exe)

The HKCU scope is appropriate for Scoop's per-user installation model.

bucket/calibre.json (3)

116-123: Uninstaller logic is correct.

The uninstaller properly imports the registry cleanup files (uninstall-associations.reg and unregister-url-handler.reg) and correctly guards execution with $cmd -eq 'uninstall'. This addresses the issue flagged in a previous review.


21-28: Pre-install configuration migration logic is sound.

The script correctly:

  1. Ensures the persist directory exists
  2. Short-circuits if config already migrated
  3. Checks both CALIBRE_CONFIG_DIRECTORY env var and default APPDATA location
  4. Migrates existing configuration with clear user feedback

68-73: Environment variables properly configure portable-like behavior.

Setting CALIBRE_NO_DEFAULT_PROGRAMS=1 prevents automatic file association registration, allowing users to opt-in via manual registry import as documented in the notes. The temp, cache, and config directories are correctly pointed to persistent locations.

scripts/calibre/uninstall-associations.reg (1)

1-357: Uninstall registry file correctly removes all Calibre file associations.

The script properly deletes both the OpenWithProgIDs registry values and the corresponding class key definitions for all 40 file extensions. Registry syntax is correct—removing values with "name"=- and deleting keys with [-HKEY_PATH] will recursively delete all subkeys. Extension coverage matches install-associations.reg with no omissions.

@SorYoshino
Copy link
Contributor Author

/verify

@github-actions
Copy link
Contributor

github-actions bot commented Jan 3, 2026

All changes look good.

Wait for review from human collaborators.

calibre-normal

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate
  • Autoupdate Hash Extraction

calibre

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate
  • Autoupdate Hash Extraction

Check the full log for details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Calibre portable installation issue [email protected]: URL scheme doesn't work

1 participant